﻿using System;
using System.Collections.Generic;
using System.Windows.Forms;
using Assist;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
using YArchitech.Controls;
using YJKArchUtils.Utils;

namespace YJKRevitAxisModule
{
	public class SortAxisBy2Pt
	{
		public SortAxisBy2Pt(ExternalCommandData cmdData)
		{
			this.m_Revit = cmdData;
			this.m_Doc = this.m_Revit.Application.ActiveUIDocument.Document;
		}

		public Result Sort(ref string message, ExternalCommandData ecd)
		{
			Result result;
			try
			{
				SortAxisForm sortAxisForm = new SortAxisForm(this.m_Revit);
				if (sortAxisForm.ShowDialog() != DialogResult.OK)
				{
					result = Autodesk.Revit.UI.Result.Cancelled;
				}
				else
				{
					string newName2 = sortAxisForm.NewName;
					SortAxisBy2Pt.GridInfos mainGridInfos = null;
					if (!this.SelectGrid("选择与排序轴线都相交的一根轴线", ref mainGridInfos, ref message))
					{
						result = Autodesk.Revit.UI.Result.Cancelled;
					}
					else
					{
						List<SortAxisBy2Pt.SortGridInfos> list;
						SortAxisBy2Pt.ReNameTag rn;
						for (;;)
						{
							IL_3E:
							SortAxisBy2Pt.SortGridInfos startGridInfos = null;
							if (!this.SelectIntersectGrid("选择要修改的起始轴线", mainGridInfos, null, ref startGridInfos))
							{
								break;
							}
							SortAxisBy2Pt.SortGridInfos endGridInfos = null;
							if (!this.SelectIntersectGrid("选择要修改的终止轴线", mainGridInfos, startGridInfos, ref endGridInfos))
							{
								goto Block_5;
							}
							list = new List<SortAxisBy2Pt.SortGridInfos>();
							if (!this.GetSortGrids(mainGridInfos, startGridInfos, endGridInfos, ref list))
							{
								goto Block_6;
							}
							rn = SortAxisBy2Pt.ReNameTag.AutoSort;
							using (List<string>.Enumerator enumerator = AxisNameManager.CalculatSortedName(newName2, list.Count).GetEnumerator())
							{
								while (enumerator.MoveNext())
								{
									string newName = enumerator.Current;
									if (list.FindIndex((SortAxisBy2Pt.SortGridInfos s) => s.Name().CompareTo(newName) == 0) == -1 && AxisNameManager.NumberIsAlreadyExisting(this.m_Doc, newName))
									{
										TaskDialog taskDialog = new TaskDialog("轴号重名");
                                        TaskDialogCommonButtons commonButtons = (TaskDialogCommonButtons)9;
										taskDialog.CommonButtons = commonButtons;
										taskDialog.AddCommandLink((TaskDialogCommandLinkId)1001, "重新选择起始轴线");
										taskDialog.AddCommandLink((TaskDialogCommandLinkId)1002, "将重名轴线自动向后排序");
										taskDialog.AddCommandLink((TaskDialogCommandLinkId)1003, "将重名轴线加‘_’后缀");
										taskDialog.TitleAutoPrefix = false;
										TaskDialogResult taskDialogResult = taskDialog.Show();
                                        if ((int)taskDialogResult == 1001)
										{
											goto IL_3E;
										}
                                        if ((int)taskDialogResult == 1002)
										{
											rn = SortAxisBy2Pt.ReNameTag.AutoSort;
											break;
										}
                                        if ((int)taskDialogResult == 1003)
										{
											rn = SortAxisBy2Pt.ReNameTag.Underline;
											break;
										}
										return Autodesk.Revit.UI.Result.Failed;
									}
								}
							}
							goto IL_193;
						}
						return Autodesk.Revit.UI.Result.Cancelled;
						Block_5:
						return Autodesk.Revit.UI.Result.Cancelled;
						Block_6:
						return Autodesk.Revit.UI.Result.Failed;
						IL_193:
						this.ChangeSortedGrid(newName2, list, rn);
						this.m_Revit.Application.ActiveUIDocument.Document.Regenerate();
						this.m_Revit.Application.ActiveUIDocument.RefreshActiveView();
						result = Autodesk.Revit.UI.Result.Succeeded;
					}
				}
			}
			catch
			{
				result = Autodesk.Revit.UI.Result.Succeeded;
			}
			return result;
		}

		private bool SelectIntersectGrid(string statusPrompt, SortAxisBy2Pt.GridInfos mainGridInfos, SortAxisBy2Pt.SortGridInfos startGridInfos, ref SortAxisBy2Pt.SortGridInfos sortGridInfos)
		{
			SortAxisBy2Pt.GridInfos gridInfos = null;
			string text = "";
			while (this.SelectGrid(statusPrompt, ref gridInfos, ref text))
			{
				double sortValue = 0.0;
				if (!this.IsIntersectGrid(mainGridInfos, gridInfos, ref sortValue))
				{
					YJKMessageBox.Show("选择的轴线与参考轴线无交点，请重新选择！");
				}
				else
				{
					if (startGridInfos == null || !startGridInfos.TheGridInfos.IsEqual(gridInfos))
					{
						sortGridInfos = new SortAxisBy2Pt.SortGridInfos(gridInfos, sortValue);
						return true;
					}
					YJKMessageBox.Show("选择的起始轴线与终止轴线相同，请重新选择终止轴线！");
				}
			}
			return false;
		}

		private bool IsIntersectGrid(SortAxisBy2Pt.GridInfos mainGridInfos, SortAxisBy2Pt.GridInfos secondGridInfos, ref double distanceToStart)
		{
			double num = 0.0;
			for (int i = 0; i < mainGridInfos.Edges.Count; i++)
			{
				EdgeInfo edgeInfo = mainGridInfos.Edges[i];
				Curve curve = edgeInfo.ConvertTo(this.m_Revit.Application.Application);
				foreach (EdgeInfo edgeInfo2 in secondGridInfos.Edges)
				{
					Curve curve2 = edgeInfo2.ConvertTo(this.m_Revit.Application.Application);
					IntersectionResultArray intersectionResultArray;
                    if ((int)curve.Intersect(curve2, out intersectionResultArray) == 8 && intersectionResultArray.Size != 0)
					{
						XYZ xyzpoint = intersectionResultArray.get_Item(0).XYZPoint;
						num += edgeInfo.DistanceToStart(xyzpoint);
						distanceToStart = num;
						return true;
					}
				}
				num += edgeInfo.Length();
			}
			return false;
		}

		private bool GetSortGrids(SortAxisBy2Pt.GridInfos mainGridInfos, SortAxisBy2Pt.SortGridInfos startGridInfos, SortAxisBy2Pt.SortGridInfos endGridInfos, ref List<SortAxisBy2Pt.SortGridInfos> intersectGrids)
		{
			bool flag = Geometry.LessThan(endGridInfos.SortValue, startGridInfos.SortValue);
			foreach (SortAxisBy2Pt.GridInfos gridInfos in this.GetAllGridInfos())
			{
				if (!gridInfos.IsEqual(mainGridInfos) && !gridInfos.IsEqual(startGridInfos.TheGridInfos) && !gridInfos.IsEqual(endGridInfos.TheGridInfos))
				{
					double num = 0.0;
					if (this.IsIntersectGrid(mainGridInfos, gridInfos, ref num))
					{
						if (flag)
						{
							if (Geometry.GreaterThan(num, endGridInfos.SortValue) && Geometry.LessThan(num, startGridInfos.SortValue))
							{
								SortAxisBy2Pt.SortGridInfos item = new SortAxisBy2Pt.SortGridInfos(gridInfos, num);
								intersectGrids.Add(item);
							}
						}
						else if (Geometry.GreaterThan(num, startGridInfos.SortValue) && Geometry.LessThan(num, endGridInfos.SortValue))
						{
							SortAxisBy2Pt.SortGridInfos item2 = new SortAxisBy2Pt.SortGridInfos(gridInfos, num);
							intersectGrids.Add(item2);
						}
					}
				}
			}
			intersectGrids.Add(startGridInfos);
			intersectGrids.Add(endGridInfos);
			intersectGrids.Sort((SortAxisBy2Pt.SortGridInfos left, SortAxisBy2Pt.SortGridInfos right) => left.SortValue.CompareTo(right.SortValue));
			if (flag)
			{
				intersectGrids.Reverse();
			}
			return true;
		}

		private List<SortAxisBy2Pt.GridInfos> GetAllGridInfos()
		{
			List<SortAxisBy2Pt.GridInfos> list = new List<SortAxisBy2Pt.GridInfos>();
			IEnumerable<Element> enumerable = new FilteredElementCollector(this.m_Doc, this.m_Doc.ActiveView.Id).OfClass(typeof(MultiSegmentGrid)).ToElements();
			List<ElementId> list2 = new List<ElementId>();
			foreach (Element element in enumerable)
			{
				MultiSegmentGrid multiSegmentGrid = element as MultiSegmentGrid;
				if (multiSegmentGrid != null)
				{
					SortAxisBy2Pt.GridInfos item = new SortAxisBy2Pt.GridInfos(element, this.m_Doc);
					list.Add(item);
					foreach (ElementId item2 in multiSegmentGrid.GetGridIds())
					{
						list2.Add(item2);
					}
				}
			}
			IEnumerator<Element> enumerator = new FilteredElementCollector(this.m_Doc, this.m_Doc.ActiveView.Id).OfClass(typeof(Grid)).ToElements().GetEnumerator();
			{
				while (enumerator.MoveNext())
				{
					Element ele = enumerator.Current;
					if (list2.FindIndex((ElementId s) => s.Compare(ele.Id) == 0) < 0)
					{
						SortAxisBy2Pt.GridInfos item3 = new SortAxisBy2Pt.GridInfos(ele, this.m_Doc);
						list.Add(item3);
					}
				}
			}
			return list;
		}

		private bool SelectGrid(string statusPrompt, ref SortAxisBy2Pt.GridInfos gridInfo, ref string message)
		{
			Selection selection = this.m_Revit.Application.ActiveUIDocument.Selection;
			try
			{
				AxisFilter axisFilter = new AxisFilter();
				Reference reference = selection.PickObject((Autodesk.Revit.UI.Selection.ObjectType)1, axisFilter, statusPrompt);
				Element element = this.m_Revit.Application.ActiveUIDocument.Document.GetElement(reference);
				if (element.GetType() == typeof(MultiSegmentGrid) || element.GetType() == typeof(Grid))
				{
					gridInfo = new SortAxisBy2Pt.GridInfos(element, this.m_Doc);
					return true;
				}
			}
			catch (Exception)
			{
				return false;
			}
			return false;
		}

		private void ChangeSortedGrid(string startName, List<SortAxisBy2Pt.SortGridInfos> sortedGrids, SortAxisBy2Pt.ReNameTag rn)
		{
			Document document = this.m_Revit.Application.ActiveUIDocument.Document;
			List<string> list = AxisNameManager.CalculatSortedName(startName, sortedGrids.Count);
			if (rn == SortAxisBy2Pt.ReNameTag.Underline)
			{
				using (List<string>.Enumerator enumerator = list.GetEnumerator())
				{
					while (enumerator.MoveNext())
					{
						string str = enumerator.Current;
						if (sortedGrids.FindIndex((SortAxisBy2Pt.SortGridInfos s) => s.Name().CompareTo(str) == 0) == -1)
						{
							SubTransaction subTransaction = new SubTransaction(document);
							try
							{
								Element element = AxisNameManager.FindNameGetGrid(str, document);
								if (element != null && element.Name == str)
								{
									subTransaction.Start();
									element.Name += "_";
									subTransaction.Commit();
								}
							}
							catch
							{
								subTransaction.RollBack();
							}
						}
					}
					goto IL_F0;
				}
			}
			if (rn == SortAxisBy2Pt.ReNameTag.AutoSort)
			{
				this.ChangeSortedGridByAutoSort(startName, ref sortedGrids, ref list);
			}
			IL_F0:
			this.m_Revit.Application.ActiveUIDocument.Document.Regenerate();
			this.m_Revit.Application.ActiveUIDocument.RefreshActiveView();
			new AxisNameManager(this.m_Revit);
			for (int i = 0; i < sortedGrids.Count; i++)
			{
				SortAxisBy2Pt.SortGridInfos sortGridInfos = sortedGrids[i];
				string newName = list[i];
				int num = sortedGrids.FindIndex((SortAxisBy2Pt.SortGridInfos value) => newName.CompareTo(value.Name()) == 0);
				if (num != -1)
				{
					string name = "temp" + i.ToString();
					sortedGrids[num].SetName(name, document);
				}
				sortGridInfos.SetName(newName, document);
			}
		}

		private void ChangeSortedGridByAutoSort(string startName, ref List<SortAxisBy2Pt.SortGridInfos> sortedGrids, ref List<string> newNames)
		{
			Document document = this.m_Revit.Application.ActiveUIDocument.Document;
			List<string> list = AxisNameManager.CalculatSortedName(startName, sortedGrids.Count);
			List<string> list2 = new List<string>();
			using (List<string>.Enumerator enumerator = list.GetEnumerator())
			{
				while (enumerator.MoveNext())
				{
					string newName = enumerator.Current;
					if (AxisNameManager.NumberIsAlreadyExisting(document, newName) && sortedGrids.FindIndex((SortAxisBy2Pt.SortGridInfos value) => newName.CompareTo(value.Name()) == 0) == -1)
					{
						list2.Add(newName);
					}
				}
			}
			if (list2.Count > 0)
			{
				AxisNameManager axisNameManager = new AxisNameManager(this.m_Revit);
				for (int i = 0; i < list2.Count; i++)
				{
					axisNameManager.AddNewName(list2[i]);
				}
			}
		}

		private ExternalCommandData m_Revit;

		private Document m_Doc;

		public const double _epsDouble = 1E-09;

		private class GridInfos
		{
			public Element Grid { get; set; }

			public List<EdgeInfo> Edges { get; set; }

			private GridInfos()
			{
			}

			public GridInfos(SortAxisBy2Pt.GridInfos infos)
			{
				this.Grid = infos.Grid;
				this.Edges = infos.Edges;
			}

			public GridInfos(Element gridElement, Autodesk.Revit.DB.Document doc)
			{
				this.Grid = gridElement;
				this.Edges = new List<EdgeInfo>();
				if (gridElement.GetType() == typeof(Grid))
				{
					EdgeInfo item = new EdgeInfo((gridElement as Grid).Curve, false);
					this.Edges.Add(item);
					return;
				}
				if (gridElement.GetType() == typeof(MultiSegmentGrid))
				{
					foreach (ElementId elementId in (gridElement as MultiSegmentGrid).GetGridIds())
					{
						Grid grid = doc.GetElement(elementId) as Grid;
						if (grid != null)
						{
							EdgeInfo edgeInfo = new EdgeInfo(grid.Curve, false);
							if (this.Edges.Count == 1 && !Geometry.IsEqual(this.Edges[0].EndPoint, edgeInfo.StartPoint) && !Geometry.IsEqual(this.Edges[0].EndPoint, edgeInfo.EndPoint))
							{
								this.Edges[0].ReverseSelf();
							}
							if (this.Edges.Count >= 1 && !Geometry.IsEqual(this.Edges[this.Edges.Count - 1].EndPoint, edgeInfo.StartPoint))
							{
								edgeInfo.ReverseSelf();
							}
							this.Edges.Add(edgeInfo);
						}
					}
				}
			}

			public bool IsEqual(SortAxisBy2Pt.GridInfos gridInfos)
			{
				return this.Grid.Id.IntegerValue == gridInfos.Grid.Id.IntegerValue;
			}
		}

		private class SortGridInfos
		{
			public SortAxisBy2Pt.GridInfos TheGridInfos { get; set; }

			public double SortValue { get; set; }

			private SortGridInfos()
			{
			}

			public SortGridInfos(SortAxisBy2Pt.SortGridInfos infos)
			{
				this.TheGridInfos = infos.TheGridInfos;
				this.SortValue = infos.SortValue;
			}

			public SortGridInfos(SortAxisBy2Pt.GridInfos gridInfos, double sortValue)
			{
				this.TheGridInfos = gridInfos;
				this.SortValue = sortValue;
			}

			public bool IsEqual(SortAxisBy2Pt.SortGridInfos sortGridInfos)
			{
				return this.TheGridInfos.IsEqual(sortGridInfos.TheGridInfos);
			}

			public string Name()
			{
				return this.TheGridInfos.Grid.Name;
			}

			public void SetName(string name, Autodesk.Revit.DB.Document doc)
			{
				if (this.TheGridInfos.Grid.GetType() == typeof(MultiSegmentGrid))
				{
					(this.TheGridInfos.Grid as MultiSegmentGrid).Text = name;
					doc.Regenerate();
					return;
				}
				if (this.TheGridInfos.Grid.GetType() == typeof(Grid))
				{
					this.TheGridInfos.Grid.Name = name;
				}
			}
		}

		public enum ReNameTag
		{
			AutoSort,
			Underline
		}
	}
}
